package com.rickpan.service;

import com.rickpan.entity.DeveloperConfig;
import com.rickpan.entity.DeveloperSession;
import com.rickpan.repository.DeveloperConfigRepository;
import com.rickpan.repository.DeveloperSessionRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Optional;
import java.util.UUID;

/**
 * 开发者访问控制服务
 * 负责开发者工具的权限验证和会话管理
 * 
 * @author 开发团队协调员
 * @since 2025-07-17
 */
@Service
public class DeveloperAccessService {

    private static final Logger logger = LoggerFactory.getLogger(DeveloperAccessService.class);

    @Autowired
    private DeveloperConfigRepository developerConfigRepository;

    @Autowired
    private DeveloperSessionRepository developerSessionRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 验证开发者密码并创建会话
     * 
     * @param userId 用户ID
     * @param password 输入的密码
     * @param ipAddress IP地址
     * @param userAgent 用户代理
     * @return 会话令牌，验证失败返回null
     */
    @Transactional
    public String authenticateAndCreateSession(Long userId, String password, String ipAddress, String userAgent) {
        try {
            // 1. 检查开发者工具是否启用
            if (!isDeveloperAccessEnabled()) {
                logger.warn("🚫 开发者工具访问已禁用: userId={}", userId);
                return null;
            }

            // 2. 验证密码
            if (!verifyDeveloperPassword(password)) {
                logger.warn("🚫 开发者密码验证失败: userId={}, ip={}", userId, ipAddress);
                logAccessAttempt(userId, "PASSWORD_VERIFY", null, ipAddress, userAgent, false, "密码错误");
                return null;
            }

            // 3. 清理用户的过期会话
            cleanupExpiredSessions(userId);

            // 4. 创建新会话
            String sessionToken = generateSessionToken();
            int timeoutSeconds = getDeveloperSessionTimeout();
            LocalDateTime expiresAt = LocalDateTime.now().plusSeconds(timeoutSeconds);

            DeveloperSession session = new DeveloperSession();
            session.setUserId(userId);
            session.setSessionToken(sessionToken);
            session.setExpiresAt(expiresAt);
            session.setIpAddress(ipAddress);
            session.setUserAgent(userAgent);

            developerSessionRepository.save(session);

            logger.info("✅ 开发者会话创建成功: userId={}, token={}, expiresAt={}", 
                       userId, sessionToken.substring(0, 8) + "...", expiresAt);

            logAccessAttempt(userId, "SESSION_CREATE", "developer_tools", ipAddress, userAgent, true, null);

            return sessionToken;

        } catch (Exception e) {
            logger.error("❌ 开发者认证失败", e);
            logAccessAttempt(userId, "SESSION_CREATE", null, ipAddress, userAgent, false, e.getMessage());
            return null;
        }
    }

    /**
     * 验证会话令牌
     * 
     * @param sessionToken 会话令牌
     * @return 用户ID，验证失败返回null
     */
    public Long validateSession(String sessionToken) {
        if (sessionToken == null || sessionToken.trim().isEmpty()) {
            return null;
        }

        try {
            Optional<DeveloperSession> sessionOpt = developerSessionRepository.findBySessionToken(sessionToken);
            
            if (sessionOpt.isEmpty()) {
                logger.debug("🚫 会话令牌不存在: token={}", sessionToken.substring(0, 8) + "...");
                return null;
            }

            DeveloperSession session = sessionOpt.get();
            
            if (session.isExpired()) {
                logger.debug("🚫 会话已过期: token={}, expiresAt={}", 
                           sessionToken.substring(0, 8) + "...", session.getExpiresAt());
                // 删除过期会话
                developerSessionRepository.delete(session);
                return null;
            }

            logger.debug("✅ 会话验证成功: userId={}, token={}", 
                        session.getUserId(), sessionToken.substring(0, 8) + "...");
            
            return session.getUserId();

        } catch (Exception e) {
            logger.error("❌ 会话验证异常", e);
            return null;
        }
    }

    /**
     * 销毁会话
     * 
     * @param sessionToken 会话令牌
     */
    @Transactional
    public void destroySession(String sessionToken) {
        try {
            Optional<DeveloperSession> sessionOpt = developerSessionRepository.findBySessionToken(sessionToken);
            
            if (sessionOpt.isPresent()) {
                DeveloperSession session = sessionOpt.get();
                developerSessionRepository.delete(session);
                
                logger.info("🗑️ 开发者会话已销毁: userId={}, token={}", 
                           session.getUserId(), sessionToken.substring(0, 8) + "...");
                
                logAccessAttempt(session.getUserId(), "SESSION_DESTROY", "developer_tools", 
                               null, null, true, null);
            }
        } catch (Exception e) {
            logger.error("❌ 销毁会话失败", e);
        }
    }

    /**
     * 验证开发者密码
     */
    private boolean verifyDeveloperPassword(String inputPassword) {
        try {
            Optional<DeveloperConfig> configOpt = developerConfigRepository
                .findByConfigKey(DeveloperConfig.DEVELOPER_PASSWORD_KEY);
            
            if (configOpt.isEmpty()) {
                logger.error("❌ 开发者密码配置不存在");
                return false;
            }

            String storedPassword = configOpt.get().getConfigValue();
            return passwordEncoder.matches(inputPassword, storedPassword);
            
        } catch (Exception e) {
            logger.error("❌ 密码验证异常", e);
            return false;
        }
    }

    /**
     * 检查开发者工具是否启用
     */
    private boolean isDeveloperAccessEnabled() {
        try {
            Optional<DeveloperConfig> configOpt = developerConfigRepository
                .findByConfigKey(DeveloperConfig.DEVELOPER_ENABLED_KEY);
            
            return configOpt.map(config -> "true".equalsIgnoreCase(config.getConfigValue()))
                           .orElse(false);
        } catch (Exception e) {
            logger.error("❌ 检查开发者工具启用状态失败", e);
            return false;
        }
    }

    /**
     * 获取会话超时时间
     */
    private int getDeveloperSessionTimeout() {
        try {
            Optional<DeveloperConfig> configOpt = developerConfigRepository
                .findByConfigKey(DeveloperConfig.SESSION_TIMEOUT_KEY);
            
            return configOpt.map(config -> Integer.parseInt(config.getConfigValue()))
                           .orElse(3600); // 默认1小时
        } catch (Exception e) {
            logger.error("❌ 获取会话超时时间失败", e);
            return 3600;
        }
    }

    /**
     * 生成会话令牌
     */
    private String generateSessionToken() {
        return "dev_" + UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 清理过期会话
     */
    @Transactional
    public void cleanupExpiredSessions(Long userId) {
        try {
            LocalDateTime now = LocalDateTime.now();
            int deletedCount = developerSessionRepository.deleteByUserIdAndExpiresAtBefore(userId, now);
            
            if (deletedCount > 0) {
                logger.info("🧹 清理过期会话: userId={}, count={}", userId, deletedCount);
            }
        } catch (Exception e) {
            logger.error("❌ 清理过期会话失败", e);
        }
    }

    /**
     * 记录访问日志
     */
    private void logAccessAttempt(Long userId, String action, String resource, 
                                 String ipAddress, String userAgent, 
                                 boolean success, String errorMessage) {
        // 这里可以实现访问日志记录
        // 为了简化，暂时只记录到应用日志
        if (success) {
            logger.info("📊 开发者访问: userId={}, action={}, resource={}, ip={}", 
                       userId, action, resource, ipAddress);
        } else {
            logger.warn("📊 开发者访问失败: userId={}, action={}, error={}, ip={}", 
                       userId, action, errorMessage, ipAddress);
        }
    }

    /**
     * 更新开发者密码
     * 
     * @param newPassword 新密码
     * @param operatorId 操作者ID
     * @return 是否成功
     */
    @Transactional
    public boolean updateDeveloperPassword(String newPassword, Long operatorId) {
        try {
            String encodedPassword = passwordEncoder.encode(newPassword);
            
            Optional<DeveloperConfig> configOpt = developerConfigRepository
                .findByConfigKey(DeveloperConfig.DEVELOPER_PASSWORD_KEY);
            
            if (configOpt.isPresent()) {
                DeveloperConfig config = configOpt.get();
                config.setConfigValue(encodedPassword);
                config.setUpdatedBy(operatorId);
                developerConfigRepository.save(config);
            } else {
                // 创建新配置
                DeveloperConfig config = new DeveloperConfig();
                config.setConfigKey(DeveloperConfig.DEVELOPER_PASSWORD_KEY);
                config.setConfigValue(encodedPassword);
                config.setDescription("RabbitMQ压测工具访问密码");
                config.setIsEncrypted(true);
                config.setCreatedBy(operatorId);
                config.setUpdatedBy(operatorId);
                developerConfigRepository.save(config);
            }
            
            logger.info("🔐 开发者密码已更新: operatorId={}", operatorId);
            return true;
            
        } catch (Exception e) {
            logger.error("❌ 更新开发者密码失败", e);
            return false;
        }
    }
}
